在大型專案中,可能會把專案依功能、架構等等因素,切分為多個子專案,雖然切分為多個子專案,有些邏輯可能還是有類似的地方,例如前端或後端的部署可能只有環境變數的不同,但流程是相同的,這時候如果可以使用的共同的部署流程就避免維護重複維護的問題。那麼,在 GitLab CI 的流程中可以怎麼完成呢?
在這系列的 GitLab 群組「GitLab PlayGround」中,有一個包含測試的 PHP Laravel 專案「i5-repository-sample」,其已經有基本的 GitLab CI 流程作 Laravel 專案測試,如果我們要在同一群組的「GitLab CI Try」啟動這個這個流水線的測試,我們應該怎麼做呢?請看底下的範例:
staging:
stage: test
trigger: mouson-gitlab-playground/i5-repository-sample
如上面的這個範例,只需要使用 trigger
這個參數,並且在後方加上對應群組及專案的名稱,就可以啟動該專案主分支上的流水線。其執行的畫面成果中,出現了新的流水線名為「Downstream」可以解讀為「下游」,由目前這個流水線而產出的新流水線。
另外,在下游專案中的流水線上,也可以看到目前流水線啟動的狀態,這邊以「Upstream」表示啟動這次流水線的專案。
這邊提到了,只設定群組及專案名稱預設啟動的是該專案上的主分支上的流水線,這時候,如果想要啟動的流水線並非在主分支上該怎麼調整呢?
staging:
stage: test
trigger:
project: mouson-gitlab-playground/i5-repository-sample
branch: master
如上面的這個範例,只需要調整增加設定 trigger
的兩個子參數 project
及 branch
即可,範例中,啟動的是該專案的 master
分支上的流水線。
一般專案在觸發其他專案開始進流水線後,主流水線後續的專案也會開始執行,如底下的例子,在 test-job
完成觸發下游流水線工作後,緊接著會開始執行 deploy-job
的工作:
test-job:
stage: test
trigger:
project: mouson-gitlab-playground/i5-repository-sample
branch: master
deploy-job:
stage: deploy
script:
- echo 'Job Total Finish'
如上圖,下游工作還沒完成,但下一階段的工作已經開始了,但如果下一階段的工作跟下游的工作有關,下游的工作失敗了,上游的流水線則不繼續進行流水線工作,該怎麼設定?
在 trigger
參數中,有另外一個子參數為 strategy
當設定為 depend
時,則上游流水線會「相依」下游流水線的工作執行結果。如底下的範例:
test-job:
stage: test
trigger:
project: mouson-gitlab-playground/i5-repository-sample
branch: master
strategy: depend
deploy-job:
stage: deploy
script:
- echo 'Job Total Finish'
在上面的這個範例中,deploy-job
會等到 test-job
觸發的專案順利執行完成後才開始進行,如下圖:
在上游可以根據下游的工作狀態,來決定流水線要不要繼續往下,那麼在下游的工作,可以依據上游的狀態決定整個流水線要不要執行嗎?當然是可以的,在下游的流水線 GitLab CI 檔案裡可以增加一個新的工作判斷上游的工作狀態,其判斷的方法使用 needs:pipeline:
來做設定,範例如下:
bridge-job:
stage: test
needs:
pipeline: other/project
根據上游狀態決定要不要往下執行的這工作在 GitLab CI 的流程裡,稱為「bridge job」用來橋接上下游的工作,但它與一般工作有些許的不同,主要是在 bridge job 裡頭,允許的參數是有限的,可用的參數如下:
trigger
stage
allow_failure
rules
only
及 except
when
(只支援 on_success
、on_failure
和 always
三種狀態)extends
注意,參數中並沒有「script」也就是說,bridge job 中不允許額外行為,僅做為承接工作用。這部分也可以透過 GitLab CI Lint 檢查的時候看到,會提示:「jobs:bridge-job:needs config uses invalid types: bridge」。
另外,如上游設定了相依下游工作,下游也設定需要根據上游工作狀態決定要不要作,則可能會發生上下游流水線互鎖的狀況,上下游都無法繼續工作而 pending
,這部分必須特別注意。
那麼,在上游流水線應該怎麼傳遞變數到或參數到下游呢?在上游流水線中,可以透過 variables
參數,直接將參數傳送到下游的工作之中,像是底下這個範例:
staging:
variables:
FROM_UPSTREAM: 'from upstream'
stage: test
trigger:
project: mouson-gitlab-playground/i5-repository-sample
branch: master
在觸發下游專案的工作中,透過 variables
帶入「FROM_UPSTREAM
」這個變數,如此在下游的流水線上的每個工作,就都可以收到來自上游的環境變數。同樣以上面提到的 Laravel 專案「i5-repository-sample」為例子,在 test-1
這個工作中增加:
test-1:
extends: .test_template
after_script:
- echo "FROM_UPSTREAM is ${FROM_UPSTREAM}"
在工作執行時,就可以收到來自上游流水線的帶來的環境變數內容,執行結果如下:
在 trigger
參數中,還可以選定本地其他的 GitLab CI 檔案來執行,亦或者是在流水線中,動態產生新的 .gitlab-ci.yml
當作子流水線來啟動,這部分可以在 trigger
參數後使用 include
子參數來設定,如下範例,細節可參考 GitLab 手冊。
trigger_job:
trigger:
include: path/to/child-pipeline.yml
無論是啟動本地的其他 .gitlab-ci.yml
檔案,或者是啟動其它專案的流水線流程,其都是透過 trigger
參數來完成,GitLab CI 也因為 trigger 參數的使用,讓它在 multi-project
的大型專案中,可以更輕易地整合在一起。
接下來的章節會開始談 GitLab CI 流水線效能的議題,我是墨嗓(陳佑竹),期待這系列的文章能夠讓人有些幫助。